package comnet

import (
	"TODecider/src/pb"
	"context"
	"fmt"
	"github.com/go-zeromq/zmq4"
	"github.com/golang/protobuf/proto"
	"time"
)

/* constant parameters */
const (
	ZmqSubFullTopic = "comnet-full"
	Method          = "tcp"
	ReconnectPeriod = 5
)

var (
	sub           zmq4.Socket
	pubAddressRun string
)

func StartZmqSubscriber(pubSocket string) {
	pubAddressRun = fmt.Sprintf("%s://%s", Method, pubSocket)
	//  Prepare our subscriber
	sub = zmq4.NewSub(context.Background())
	err := sub.Dial(pubAddressRun)
	if err != nil {
		log.Errorf("[ZMQ Sub] could not dial %s: %v", pubSocket, err)
		reconnect()
	} else {
		subscribe()
	}
}

func subscribe() {
	err := sub.SetOption(zmq4.OptionSubscribe, ZmqSubFullTopic)
	if err != nil {
		log.Fatalf("[ZMQ Sub] could not subscribe: %v", err)
	}
	log.Info("[ZMQ Sub] started successfully")
	// start receiving data
	for {
		msg, err := sub.Recv()
		if err != nil {
			// try to reconnect to the publisher
			log.Errorf("[ZMQ Sub] could not receive message: %v", err)
			reconnect()
		} else {
			// store data
			comNet := pb.ComNet{}
			err = proto.Unmarshal(msg.Frames[1], &comNet)
			if err != nil {
				log.Errorf("[ZMQ Sub] could not unmarshal struct: %v", err)
				return
			}
			StoreComNet(&comNet)
		}
	}
}

func reconnect() {
	for {
		log.Debug("[ZMQ Sub] reconnecting... ")
		err := sub.Dial(pubAddressRun)
		if err != nil {
			log.Errorf("[ZMQ Sub] could not dial: %v", err)
			time.Sleep(time.Second * ReconnectPeriod)
		} else {
			break
		}
	}
	subscribe()
}
